﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Collections;
using System.Drawing;
using Maxel.MultitrackControl;
using LED_Utils.MultitrackControl;

namespace Maxel.MultitrackControl
{
	[ComplexBindingProperties("DataSource")]
    public partial class EditableTrack : ZoomableScrollableFlowLayoutPanel
	{
		public EditableTrack()
		{
			InitializeComponent();
            InternalInit();
		}



		public EditableTrack(IContainer container)
		{
			container.Add(this);

			InitializeComponent();
            InternalInit();
        }

        private void InternalInit()
        {
            _scaleFactor = 200;
        }

		private object _datasource;

		[AttributeProvider(typeof(IListSource))]
		[RefreshProperties(RefreshProperties.Repaint)]
		[DefaultValue(null)]
		[Category("Data")]
		public object DataSource
		{
			get { return _datasource; }
			set {
				_datasource = value;

				InitInternal();
			}
		}

		private void InitInternal()
		{
            if (_datasource == null)
				return;

            if (_datasource is IList)
            {
                IList listSource = (IList)_datasource;
                foreach (var item in listSource)
                {
                    AddFrameInternal(item);
                }
            }

            if (_datasource is CurrencyManager )
            {
                IList listSource = ((CurrencyManager)_datasource).List;
                foreach (var item in listSource)
                {
                    AddFrameInternal(item);
                }
            }

            //if (_datasource is IEnumerable)
            //{
            //    IEnumerable enumSource = (IEnumerable)_datasource;
            //    foreach (var item in enumSource)
            //    {
            //        AddFrameInternal(item);
            //    }
            //}



            if (_datasource is IBindingList)
            {
                IBindingList bindingListSource = (IBindingList)_datasource;
                //bindingListSource.ListChanged += bindingListSource_ListChanged;
            }

            if (_datasource is BindingSource)
            {
                BindingSource bindingSource = (BindingSource)_datasource;
                bindingSource.PositionChanged += new EventHandler(bindingSource_PositionChanged);
                bindingSource.CurrentChanged += new EventHandler(bindingSource_CurrentChanged);
                bindingSource.ListChanged += bindingListSource_ListChanged;

            }
		}

        public object Current
        {
            get
            {
                return ((BindingSource)_datasource).Current;
            }
        }
        public event EventHandler CurrentChanged;
        private void OnCurrentChanged()
        {
            if (CurrentChanged != null)
            {
                CurrentChanged(this, EventArgs.Empty);
            }
        }

        void bindingSource_CurrentChanged(object sender, EventArgs e)
        {
            OnCurrentChanged();
        }

        void bindingSource_PositionChanged(object sender, EventArgs e)
        {
            if (((BindingSource)sender).Position < 0)
                return;
           
            if (Controls.Count > ((BindingSource)sender).Position)
            {
                SelectFrameControl(Controls[((BindingSource)sender).Position]);
            }
        }

        void bindingListSource_ListChanged(object sender, ListChangedEventArgs e)
        {
            switch (e.ListChangedType )
            {
                case ListChangedType.ItemAdded:
                    AddFrameInternal(((IBindingList)sender)[e.NewIndex]);
                    break;
                case ListChangedType.ItemChanged:
                    break;
                case ListChangedType.ItemDeleted:
                    DeleteFrameInternal(e.NewIndex);
                    break;
                case ListChangedType.ItemMoved:
                    break;
                case ListChangedType.PropertyDescriptorAdded:
                    break;
                case ListChangedType.PropertyDescriptorChanged:
                    break;
                case ListChangedType.PropertyDescriptorDeleted:
                    break;
                case ListChangedType.Reset:
                    break;
                default:
                    break;
            }
        }

        private void DeleteFrameInternal(int p)
        {
           Controls.RemoveAt(p)  ;
        }

        protected virtual Control GetFrameControl()
		{
            Control panel = new FrameControl();
            panel.Margin = new Padding(1);
            panel.Padding = Padding.Empty;
            panel.Leave += EditableTrack_Leave;
            return panel; 
		}

       

       
		private void  AddFrameInternal(object obj)
		{
            Control panel = GetFrameControl();
            if (panel is IFramePanel)
            {
                //((IFramePanel)panel).StartColor = (Color)GetValue(obj, "StartColor");
                //((IFramePanel)panel).EndColor   = (Color)GetValue(obj, "EndColor");
                //((IFramePanel)panel).Duration   = (float)GetValue(obj, "FrameDuration"); 
                //((IFramePanel)panel).FramePanelProperiesChanged += new EventHandler(EditableTrack_FramePanelProperiesChanged);
                ((IFramePanel)panel).FrameData = obj;
            }
            else
            {
               // panel.BackColor = Color.PeachPuff;
            }
            if (obj is INotifyPropertyChanged)
            {
                ((INotifyPropertyChanged)obj).PropertyChanged += new PropertyChangedEventHandler(EditableTrack_PropertyChanged); 
            }
			//panel.Click += new EventHandler(panel_Click); 
            panel.MouseDown += new MouseEventHandler(panel_MouseDown);
            panel.MouseMove += new MouseEventHandler(panel_MouseMove);
            panel.MouseUp += new MouseEventHandler(panel_MouseUp);

            if (panel is ICustomScale)
            {
                ((ICustomScale)panel).InitialScale = InitialScale;
                ((ICustomScale)panel).ScaleFactor  = ScaleFactor ;
            }
           

            panel.Height = this.Height - panel.Margin.All  * 2 - panel.Padding.All  * 2;
            //Splitter splitter = new Splitter();

            //splitter.Margin = Padding.Empty;
            //splitter.Padding = Padding.Empty;
            //splitter.MinSize  = 1;
            //splitter.MinExtra  = 1;


			//splitter.Size = new System.Drawing.Size(5);

			Controls.Add(panel);
			//Controls.Add(splitter);
		}

        void EditableTrack_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            OnCurrentChanged(); 
        }

        void EditableTrack_FramePanelProperiesChanged(object sender, EventArgs e)
        {
            //throw new NotImplementedException();
            //SetValue(this.BindingContext[DataSource].Current, "FrameDuration", ((IFramePanel)sender).Duration);

        }

        bool _isMouseDown;
        void panel_MouseDown(object sender, MouseEventArgs e)
        {
            _isMouseDown = true;

            OnFrameControlClick();

            SetPositionInBindingContext((Control)sender);

            SelectFrameControl((Control)sender);

            //if (e.Button != MouseButtons.Left)
            //    return;


            //DoDragDrop(sender, DragDropEffects.Move);
        }
        void panel_MouseMove(object sender, MouseEventArgs e)
        {
            //SetPositionInBindingContext((Control)sender);

            //SelectFrameControl((Control)sender);

            if (e.Button != MouseButtons.Left || !_isMouseDown)
                return;


            DoDragDrop(sender, DragDropEffects.Move);
        }
        void panel_MouseUp(object sender, MouseEventArgs e)
        {

            //SetPositionInBindingContext((Control)sender);

            //SelectFrameControl((Control)sender);

            //if (e.Button != MouseButtons.Left)
            //    return;


            //DoDragDrop(sender, DragDropEffects.Move);
            _isMouseDown = false;

        }

        private void SetPositionInBindingContext(Control sender)
        {
            this.BindingContext[DataSource].Position = this.Controls.IndexOf(sender);
        }

        //void panel_Click(object sender, EventArgs e)
        //{
        //    SelectFramePanel((Panel)sender);
        //}

        public event EventHandler FrameControlClick;

        private void OnFrameControlClick()
        {
            if (FrameControlClick != null)
            {
                FrameControlClick(this, EventArgs.Empty);
            }
        }
        private Control _selected;
        private void SelectFrameControl(Control sender)
        {
            DeselectFrames();
            SetBorderStyle((Control)sender, BorderStyle.FixedSingle);
            _selected = sender;
            //MessageBox.Show(Controls.GetChildIndex(_selected).ToString() );
        }

        private void DeselectFrames()
        {
            SuspendLayout(); 
            foreach (Control item in Controls)
            {
                if (!(item is FrameControl))
                    continue;

                ((FrameControl)item).BorderStyle = BorderStyle.None;
            }
           ResumeLayout(); 

        }
        //private HScrollProperties _horisontalScroll;
        //public HScrollProperties HorisontalScroll
        //{
        //    get { return _horisontalScroll; }
        //     set { _horisontalScroll = value; }
        //}

        //private HScrollBar _horisontalScrollBar;
        //public HScrollBar HorisontalScrollBar
        //{
        //    get { return _horisontalScrollBar; }
        //    set
        //    {
        //        _horisontalScrollBar = value;
        //        _horisontalScrollBar.ValueChanged += delegate(object sender, EventArgs e)
        //        {
        //           SetScrollProperties();
        //        };
        //        _horisontalScrollBar.Scroll += delegate(object sender, ScrollEventArgs e)
        //        {
        //           SetScrollProperties();
        //        };
        //    }
        //}

        //private void SetScrollProperties()
        //{
        //    HScroll = false;
        //    _horisontalScrollBar.LargeChange = this.HorizontalScroll.LargeChange;
        //    _horisontalScrollBar.Maximum = this.HorizontalScroll.Maximum;
        //    _horisontalScrollBar.Minimum = this.HorizontalScroll.Minimum;
        //    _horisontalScrollBar.SmallChange = this.HorizontalScroll.SmallChange;
        //    this.HorizontalScroll.Value = _horisontalScrollBar.Value;


        //}
        protected override void OnPaint(PaintEventArgs e)
        {
           // HScroll = true;
            base.OnPaint(e);
        }

        private void RemoveFramePanel(Panel sender)
        {
            Control nextSplitter = GetNextControl(sender, true);
            if (!(nextSplitter is Splitter))
                throw new InvalidOperationException("Splitter for panel not found");

            //Controls. 
        }
        //private float _scale;
        //private float _previousScale;

        //public float ScaleFactor
        //{
        //    get {
        //        return _scale;
        //    }
        //    set {
        //        if (value <= 0.0f)
        //            return;
        //        _previousScale = _scale;
        //        _scale = value;
        //        SetFramesWidth();
        //    }
        //}

        //private void SetFramesWidth()
        //{
        //    foreach (Control item in Controls)
        //    {
        //        //item.Width = (int)(item.Width * _scale);
        //        //item.Scale(new SizeF(1, 1));
        //        item.Scale(new SizeF(_scale / _previousScale, 1));  
        //    }
        //    Invalidate(); 
        //}

        //protected override bool HScroll
        //{
        //    get;
        //    set;
        //}

        public int _scaleFactor;
        [DefaultValue(200)]
        public int ScaleFactor
        {
            get { return _scaleFactor; }
            set
            {
                _scaleFactor = value;
                Invalidate();
            }
        }


        public  void Insert(int indexAt)
        {
            if (_selected != null)
            {
                int index   = Controls.GetChildIndex (_selected);
                Controls.SetChildIndex(_selected, indexAt);
            }
            //List<Control> controlsToOffset = new List<Control>();
            //int processedPanels = 0;
            //for (int i = 0; i < Controls.Count; i++)
            //{
            //    Control current = Controls[i];
            //    if (!(current is Panel))
            //        continue;


            //    RemoveFramePanel((Panel)current);
            //}



            //}
            //this.
            //Controls.Add(panel);
           //Controls.
        }

        private void EditableTrack_DragEnter(object sender, DragEventArgs e)
        {
            e.Effect = DragDropEffects.Scroll ; 
            object o = e;
        }

        private void EditableTrack_DragDrop(object sender, DragEventArgs e)
        {
            Point currentMousePosition = MousePosition;
            Control ctrl = e.Data.GetData(typeof(FrameControl)) as Control ;
            if (ctrl == null)
                return;

            Point leftSideHitTest = new Point(currentMousePosition.X - ctrl.Padding.All - ctrl.Margin.All, currentMousePosition.Y);
            Point rightSideHitTest = new Point(currentMousePosition.X + ctrl.Padding.All + ctrl.Margin.All, currentMousePosition.Y);

            Control leftCtrl = this.GetChildAtPoint(this.PointToClient(leftSideHitTest));
            Control rightCtrl = this.GetChildAtPoint(this.PointToClient(rightSideHitTest));


            int leftIndex = Controls.GetChildIndex(leftCtrl,false);
            int rightIndex = Controls.GetChildIndex(rightCtrl, false);

            if (rightIndex == -1)
                return;
            Controls.SetChildIndex(ctrl, rightIndex);

        }

        private void EditableTrack_DragOver(object sender, DragEventArgs e)
        {
            Control ctrl = this.GetChildAtPoint(this.PointToClient(MousePosition));
            if (ctrl != null)
            {
                e.Effect = DragDropEffects.None ;
            }
            else
            {
                e.Effect = DragDropEffects.Move;
            }
        }

        private void EditableTrack_SizeChanged(object sender, EventArgs e)
        {
            foreach (Control item in Controls)
            {
                item.Height = Height;
            }
        }

        private void EditableTrack_Leave(object sender, EventArgs e)
        {
            DeselectFrames();
        }

        private void EditableTrack_Click(object sender, EventArgs e)
        {
            DeselectFrames();
            SetBorderStyle((Control)sender, BorderStyle.FixedSingle);
        }

        private void SetBorderStyle(Control control, BorderStyle borderStyle)
        {
            if (control is Panel)
            {
                ((Panel)control).BorderStyle = borderStyle;
            }
            else if (control is UserControl)
            {
                ((UserControl)control).BorderStyle = borderStyle;
            }
        }

    }
}
